import * as vscode from 'vscode';
import { unzipSync } from 'fflate';
import { MagicResourceType } from '../types';
import { MirrorFileMeta, MIRROR_FILE_CONSTANTS } from './types';
import { MirrorMetaManager } from './metaManager';
import { MagicGroupMetaRaw } from '../magicApiClient';

function toPosix(rel: string): string { return rel.replace(/\\/g, '/'); }

// 尝试从 .ms 文件头部解析 JSON 元数据并与脚本分离
function parseMsWithMeta(text: string): { meta: Record<string, any> | null; script: string } {
    // 去除 BOM
    if (text.charCodeAt(0) === 0xFEFF) text = text.slice(1);
    const lines  = text.split("\n");
    // 通过 META_SCRIPT_SEPARATOR 分隔 meta 和 script
    const dividerIndex = lines.findIndex(line => line.trim() === MIRROR_FILE_CONSTANTS.META_SCRIPT_SEPARATOR);
    if (dividerIndex > 0) {
        const metaStr = lines.slice(0, dividerIndex).join('\n').trim();
        try {
            const meta = JSON.parse(metaStr);
            const script = lines.slice(dividerIndex + 1).join('\n').trim();
            return { meta, script };
        } catch(e) {console.warn(e)}
    }

    // 默认：未提取到有效元数据，整体文本即脚本
    return { meta: null, script: text };
}

// 新增：用于让上层消费的 ZIP 条目迭代器
export type ZipYieldItem =
    | { kind: 'script'; type: MagicResourceType; groupPathSub: string; fileName: string; script: string; meta: MirrorFileMeta }
    | { kind: 'group-meta'; type: MagicResourceType; groupPathSub: string; rawText: string; parsed?: MagicGroupMetaRaw }
    | { kind: 'file'; relPath: string; data: Uint8Array };

export async function* iterateZipEntries(zipData: Uint8Array): AsyncGenerator<ZipYieldItem> {
    const files = unzipSync(zipData);
    for (const rawName of Object.keys(files)) {
        const name = toPosix(rawName);
        // 跳过目录条目
        if ((/[\\\/]$/).test(name)) continue;
        const data = files[rawName];
        const parts = name.split(/\//).filter(Boolean);
        const file = parts.pop() || '';
        const dirParts = parts;

        if (file.endsWith('.ms')) {
            const text = Buffer.from(data).toString('utf8');
            const { meta, script } = parseMsWithMeta(text);
            const type = (dirParts[0] || '') as MagicResourceType;
            const groupPathSub = dirParts.slice(1).join('/');
            const nameNoExt = file.replace(/\.ms$/, '');
            const groupPath = type ? `${type}${groupPathSub ? '/' + groupPathSub : ''}` : (meta?.groupPath || '');
            const mf: MirrorFileMeta = {
                ...(meta || {}),
                name: (meta?.name as string) || nameNoExt,
                type: (meta?.type as MagicResourceType) || type,
                groupPath,
            } as MirrorFileMeta;
            try { if (mf && (mf as any).script) delete (mf as any).script; } catch(e) {console.warn(e)}
            yield { kind: 'script', type, groupPathSub, fileName: nameNoExt, script, meta: mf };
        } else if (file === 'group.json') {
            const type = (dirParts[0] || '') as MagicResourceType;
            const groupPathSub = dirParts.slice(1).join('/');
            const rawText = Buffer.from(files[rawName]).toString('utf8');
            let parsed: MagicGroupMetaRaw | undefined;
            try { parsed = JSON.parse(rawText); } catch(e) {console.warn(e)}
            yield { kind: 'group-meta', type, groupPathSub, rawText, parsed };
        } else {
            yield { kind: 'file', relPath: name, data };
        }
    }
}
